//


/////////////////////////////////////////////
#include "common.hpp"
#include "global.hpp"
#include "filemanager.hpp"
#include "log.hpp"
/////////////////////////////////////////////
#include "statemanager.hpp"
#include "staticimage.hpp"
#include "levelmanager.hpp"
#include "GLFT_Font.hpp"
#include "bitfont.hpp"
#include "basicmenu.hpp"
#include "player.hpp"

#include "fmod.hpp"
#include "fmod_errors.h"


// [TOGGLE] CHANGE BEGINNING STATE HERE ///////////////////////////////////////////
State current = STATE_ZERO;
State next = STATE_LEVEL;//STATE_LOGO_FLASH;
/////////////////////////////////////////////
// LOGO FLASH
KEG::StaticImage logoImage;
float logoWidth=0;
float logoHeight=0;
double timeElapsed = 0;
float alpha = 0;
/////////////////////////////////////////////
// PRESENTS FLASH
GLFT_Font whiteFont;
std::string presentString( "Proudly Presents" );
//double timeElapsed = 0;
//float alpha = 0;
/////////////////////////////////////////////
// MENU
KEG::StaticImage splashBack;
KEG::StaticImage gameTitle;
//KEG::BitFont menuText;
BasicMenu mainMenu;
//StaticImage cursor;
float titleY = 50;
float titleDir = 1;
// sound
FMOD::Sound *MusicHandle;
FMOD::Channel *MusicChannel;
/////////////////////////////////////////////
// LEVEL
float camX = 0;
float camY = 0;
float moveCamX = 0;
float moveCamY = 0;

Player PJ;

//std::string menuItem[] =
//{
//	"START",
//	"EXIT"
//};

// HACK
extern int running;
extern FMOD::System *fmodSystem;

namespace StateManager
{
//void AddFutureState( State next );
//void Start();

void GLFWCALL KeyPress( int key, int action )
{
	switch(current)
{
	case STATE_ZERO:
		//error
	case STATE_LOGO_FLASH:
	case STATE_PRESENT_FLASH:
	{
		if( action == GLFW_RELEASE )
		{
			next = STATE_MENU;
			Init();
		}
		break;
	}
	case STATE_MENU_FLASH:
	{
		break;
	}
	case STATE_MENU:
	{
		if( action == GLFW_RELEASE && key == GLFW_KEY_ESC )
		{
			running = 0;
		}
		else if( action == GLFW_PRESS )
		{
			if( key == GLFW_KEY_DOWN )
				mainMenu.Down();
			else if( key == GLFW_KEY_UP )
				mainMenu.Up();
			else if( key == GLFW_KEY_ENTER )
			{
				std::string str = mainMenu.Enter();
				if( str == "EXIT" )
					running = 0;
				else if( str == "START" )
				{
					next = STATE_LEVEL;
					Init();
				}
			}

		}
		break;
	}
	case STATE_LEVEL:
	{
		if( action == GLFW_PRESS && key == GLFW_KEY_SPACE )
		{
			LevelManager::PauseMusic();
		}
		else if( action == GLFW_PRESS && key == GLFW_KEY_ENTER )
		{
			LevelManager::PlayMusic();
		}
		else if( action == GLFW_RELEASE && key == GLFW_KEY_ESC )
		{
			//LOG_RAW() << "REGISTER";
			next = STATE_MENU;
			Init();
		}
		else if( action == GLFW_PRESS && key == GLFW_KEY_RIGHT )
		{
			moveCamX = 4.0f;
		}
		else if( action == GLFW_PRESS && key == GLFW_KEY_LEFT )
		{
			moveCamX = -4.0f;
		}
		else if( action == GLFW_PRESS && key == GLFW_KEY_UP )
		{
			moveCamY = -4.0f;
		}
		else if( action == GLFW_PRESS && key == GLFW_KEY_DOWN )
		{
			moveCamY = 4.0f;
		}
		else if( action == GLFW_RELEASE && (key == GLFW_KEY_RIGHT || key == GLFW_KEY_LEFT ) )
			moveCamX = 0;
		else if( action == GLFW_RELEASE && (key == GLFW_KEY_UP || key == GLFW_KEY_DOWN ) )
			moveCamY = 0;
		break;
	}
	default:
	{
		//error
		break;
	}
}
}

void Release()
{

switch(current)
{
	case STATE_ZERO:
		//error
		break;
	case STATE_LOGO_FLASH:
	{
		glDisable(GL_BLEND);
		glEnable(GL_ALPHA_TEST);
		logoImage.Release();
		break;
	}
	case STATE_PRESENT_FLASH:
	{
		glDisable(GL_BLEND);
		glEnable(GL_ALPHA_TEST);
		glEnable(GL_TEXTURE_RECTANGLE_ARB);
		whiteFont.release();
		break;
	}
	case STATE_MENU_FLASH:
	{
		break;
	}
	case STATE_MENU:
	{
		mainMenu.Release();

		//whiteFont.release();

		splashBack.Release();
		gameTitle.Release();
		//menuText.Release();

		MusicChannel->stop();
		MusicHandle->release();
		break;
	}
	case STATE_LEVEL:
	{
		LevelManager::Unload();
		glDisable( GL_DEPTH_TEST );
		break;
	}
	default:
	{
		//error
		break;
	}
}
}

void Init()
{
	LOG_INFO( "Switching State" );

	if( next == STATE_ZERO )
		return;

	Release();

	current = next;
	next = STATE_ZERO;

	switch(current)
	{
		case STATE_ZERO:
			//error
		case STATE_LOGO_FLASH:
		{
			glEnable(GL_BLEND);
			glDisable(GL_ALPHA_TEST);
			logoImage.LoadFullImage( KEG::Path( IMAGE, "pixeljoint") );
			logoWidth = logoImage.Width();
			logoHeight = logoImage.Height();
			timeElapsed = alpha = 0;
			break;
		}
		case STATE_PRESENT_FLASH:
		{
			glEnable(GL_BLEND);
			glDisable(GL_ALPHA_TEST);
			glDisable(GL_TEXTURE_RECTANGLE_ARB);
			whiteFont.open( KEG::Path( TTF, "temp" ), 24 );
			timeElapsed = alpha = 0;
			break;
		}
		case STATE_MENU_FLASH:
		{
			// not ready yet
			next = STATE_MENU;
			Init();
			break;
		}
		case STATE_MENU:
		{
			splashBack.LoadFullImage( KEG::Path( IMAGE, "titleback" ) );
			// temp
			//whiteFont.open( KEG::Path( TTF, "temp" ), 24 );

			gameTitle.LoadFullImage( KEG::Path( IMAGE, "titleheader" ) );
			gameTitle.Height( 2*gameTitle.Height());
			gameTitle.Width( 2*gameTitle.Width());
			titleY = 50;

			//menuText.Load( KEG::Path( FONT, "white" ) );
			mainMenu.cursor.LoadFullImage( KEG::Path( IMAGE, "pjhead" ) );
			mainMenu.font.Load( KEG::Path( FONT, "white" ), 2 );
			//mainMenu.font.Release();
			//mainMenu.font.Load( KEG::Path( FONT, "white" ), 2 );
			mainMenu.menuItem.push_back( "START" );
			mainMenu.menuItem.push_back( "EXIT" );
			mainMenu.Reset();
			mainMenu.top = 280;
			mainMenu.left = 100;

			glColor4f(1,1,1,1);

			if( FMOD_OK != fmodSystem->createSound( KEG::Path( MUSIC, "options" ).c_str(),
				FMOD_LOOP_NORMAL | FMOD_2D | FMOD_CREATESTREAM, 0, &MusicHandle ) )
			{
				LOG_RAW() << "Loading Music File " << KEG::Path( MUSIC, "options" ) << std::endl;
			}
			else fmodSystem->playSound(FMOD_CHANNEL_FREE, MusicHandle, false, &MusicChannel);
			break;
		}
		case STATE_LEVEL:
		{
			glEnable( GL_DEPTH_TEST );
			PJ.Load();
			LevelManager::LoadFirstLevel();

			//set camera after level loads!
			camX = PJ.CurrentX() - Global::Game::Width/2;
			camY = PJ.CurrentY() - Global::Game::Height/2;
			//LevelManager::PlayMusic();
			break;
		}
		default:
		{
			//error
			break;
		}
	}
}

void Render()
{

	switch(current)
	{
		case STATE_ZERO:
			//error
		case STATE_LOGO_FLASH:
		{
			glColor4f( 1,1,1, alpha );
			//size
			if( timeElapsed < 2.1 )
			{
			logoImage.Width( logoWidth + logoWidth * 4 * (1.0f-alpha) );
			logoImage.Height( logoHeight + logoHeight * 16 * (1.0f-alpha) );
			}
			logoImage.RenderCentered( Global::Game::Width, Global::Game::Height );
			break;
		}
		case STATE_PRESENT_FLASH:
		{
			glColor4f( 1,1,1, alpha );
			if( timeElapsed < 2.0 )
			{
				float stringWidth = whiteFont.calcStringWidth(presentString);
				float endPos = Global::Game::Width/2 - stringWidth/2;
				float distance = endPos;// + stringWidth;
				whiteFont.drawText( endPos - (1.0f-alpha) * (distance),
					Global::Game::Height/2 - whiteFont.getHeight()/2,
					presentString );
			}
			else
			{
				float stringWidth = whiteFont.calcStringWidth(presentString);
				float startPos = Global::Game::Height/2 - whiteFont.getHeight()/2;
				float distance = Global::Game::Height - startPos;
				//whiteFont.drawText( Global::Game::Width/2 - stringWidth/2,
				//	startPos + distance * (1.0f-alpha),
				//	presentString );
				//UGLY
				glPushMatrix();
				float maxSize = (1.0f - alpha) * distance;
				float stepSize = maxSize / presentString.size() * 2;
				glTranslatef( Global::Game::Width/2 - stringWidth/2, startPos - maxSize, 0 );

				for( std::string::const_iterator itr = presentString.begin();
					itr != presentString.end();
					++itr )
				{
					whiteFont.drawRawChar(*itr);
					glTranslatef( 0, stepSize, 0 );
				}
				glPopMatrix();
			}
			break;
		}
		case STATE_MENU_FLASH:
		{
			break;
		}
		case STATE_MENU:
		{
			//splashBack.Width(10);
			//splashBack.Height(10);
			glColor3f( 0.5, 0.5, 1 );
			//glDisable(GL_TEXTURE_RECTANGLE_ARB);
			//glEnable(GL_TEXTURE_RECTANGLE_ARB);
			splashBack.Render( 0,0 );
			glColor3f(1,1,1);
			//glDisable(GL_TEXTURE_RECTANGLE_ARB);
			//glEnable(GL_TEXTURE_RECTANGLE_ARB);
			gameTitle.RenderCenteredX( titleY, Global::Game::Width );

			//std::ostringstream sstr;
			//sstr << gameTitle.Tx() << ", " << gameTitle.Ty();

			//glDisable(GL_TEXTURE_RECTANGLE_ARB);
			//whiteFont.drawText( 0, 400, sstr.str() );
			//glEnable(GL_TEXTURE_RECTANGLE_ARB);

			//TEMP
			//menuText.RenderTextCentered( "START", 280, Global::Game::Width );
			//menuText.RenderTextCentered( "EXIT", 335, Global::Game::Width );
			
			//if( GLFW_PRESS == glfwGetKey(GLFW_KEY_SPACE) )
			//{
				glEnable(GL_TEXTURE_RECTANGLE_ARB);
				mainMenu.Render();
			//}

			break;
		}
		case STATE_LEVEL:
		{
			PJ.Render(camX, camY);
			LevelManager::Render(camX, camY);
			LevelManager::RenderForeground(camX, camY);
			break;
		}
		default:
		{
			//error
			break;
		}
	}

}

void Update( double frameTime )
{

	switch(current)
	{
		case STATE_ZERO:
			//error
		case STATE_LOGO_FLASH:
		{
			timeElapsed += frameTime;
			if( timeElapsed > 5.0 )
			{
				next = STATE_PRESENT_FLASH;
				Init();
			}
			else if( timeElapsed > 3.0  )
			{
				alpha -= frameTime * 0.5;
			}
			else if( timeElapsed > 2.0 )
			{
				alpha = 1;
			}
			else // switch state
			{
				alpha += frameTime * 0.5;
			}
			break;
		}
		case STATE_PRESENT_FLASH:
		{
			timeElapsed += frameTime;
			if( timeElapsed > 3.0 )
			{
				next = STATE_MENU_FLASH;
				Init();
			}
			else if( timeElapsed > 2.0  )
			{
				alpha -= frameTime * 1;
			}
			else if( timeElapsed > 1.0 )
			{
				alpha = 1;
			}
			else // switch state
			{
				alpha += frameTime * 1.0;
			}
			break;
		}
		case STATE_MENU_FLASH:
		{
			break;
		}
		case STATE_MENU:
		{
			titleY += frameTime * titleDir * 75;
			if( titleY > 65 )
			{
				titleY = 65 -titleY +65;
				titleDir = - titleDir;
			}
			else if( titleY < 50 )
			{
				titleY = 50 + 50-titleY;
				titleDir = - titleDir;
			}

			mainMenu.Update( frameTime );

			//if( GLFW_PRESS == glfwGetKey(GLFW_KEY_KP_8) )
			//{
			//	gameTitle.AddTy(-1);
			//}
			//else if( GLFW_PRESS == glfwGetKey(GLFW_KEY_KP_4) )
			//{
			//	gameTitle.AddTx(-1);
			//}
			//else if( GLFW_PRESS == glfwGetKey(GLFW_KEY_KP_6) )
			//{
			//	gameTitle.AddTx(1);
			//}
			//else if( GLFW_PRESS == glfwGetKey(GLFW_KEY_KP_2) )
			//{
			//	gameTitle.AddTy(1);
			//}

			break;
		}
		case STATE_LEVEL:
		{
			camX += moveCamX;
			camY += moveCamY;
			break;
		}
		default:
		{
			//error
			break;
		}
	} // switch

} // Update()

} // namespace StateManager
